package com.xy.math;

public class FloatUtils {
	/**
	 * 解析16位表示的浮点数。
	 */
	public static float decompress16(short hbits) {
		int mant = hbits & 0x03ff; 	// 10 bits mantissa
		int exp = hbits & 0x7c00; 	// 5 bits exponent
		if (exp == 0x7c00) 			// NaN/Inf
			exp = 0x3fc00; 			// -> NaN/Inf
		else if (exp != 0) { 		// normalized value
			exp += 0x1c000; 		// exp - 15 + 127
			if (mant == 0 && exp > 0x1c400) // smooth transition
				return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff);
		} else if (mant != 0) { 	// && exp==0 -> subnormal
			exp = 0x1c400; 			// make it normal
			do {
				mant <<= 1; 		// mantissa * 2
				exp -= 0x400; 		// decrease exp by 1
			} while ((mant & 0x400) == 0); // while not normal
			mant &= 0x3ff; 			// discard subnormal bit
		} 							// else +/-0 -> +/-0
		return Float.intBitsToFloat( // combine all parts
				(hbits & 0x8000) << 16 // sign << ( 31 - 15 )
						| (exp | mant) << 13); // value << ( 23 - 10 )
	}

	/**
	 * 把浮点数压缩位16位表示。
	 */
	public static short compress16(float fval) {
		int fbits = Float.floatToIntBits(fval);
		int sign = fbits >>> 16 & 0x8000; // sign only
		int val = (fbits & 0x7fffffff) + 0x1000; // rounded value

		if (val >= 0x47800000) // might be or become NaN/Inf
		{ // avoid Inf due to rounding
			if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become
														// NaN/Inf
				if (val < 0x7f800000) // was value but too large
					return (short)(sign | 0x7c00); // make it +/-Inf
				return (short)(sign | 0x7c00 | // remains +/-Inf or NaN
						(fbits & 0x007fffff) >>> 13); // keep NaN (and Inf) bits
			}
			return (short)(sign | 0x7bff); // unrounded not quite Inf
		}
		if (val >= 0x38800000) // remains normalized value
			return (short)(sign | ((val - 0x38000000) >>> 13)); // exp - 127 + 15
		if (val < 0x33000000) // too small for subnormal
			return (short)sign; // becomes +/-0
		val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc
		return (short)(sign | (((fbits & 0x7fffff | 0x800000) // add subnormal bit
				+ (0x800000 >>> (val - 102))) // round depending on cut off
				>>> (126 - val))); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0
	}
	
	/**
	 * 解析一个8位表示的浮点数， 仅用于-1到1之间的浮点数。
	 */
	public static float decompress8(byte value)
	{
		return ((((int)value) & 0xFF) - 128) / 100.0f;
	}

	/**
	 * 把浮点数压缩为8位表示， 仅用于-1到1之间的浮点数。
	 */
	public static byte compress8(float value)
	{
		return (byte)((value * 100.0f + 0.5f) + 128);
	}
	
	public static void main(String[] args) {
		float f1 = 0.8954272f;
		float f2 = 0.454136f;
		
		byte f11 = compress8(f1);
		byte f12 = compress8(f2);
		
		float d1 = decompress8(f11);
		float d2 = decompress8(f12);
		
		float angle = FastMath.getAngle(new Vector2f(f1, f2));
		float angle2 = FastMath.getAngle(new Vector2f(d1, d2));
		
		System.out.println("d1=" + d1 + ",d2=" + d2 + "\na1=" + angle + ",a2=" + angle2);
		
		short f111 = compress16(f1);
		short f112 = compress16(f2);
		
		float d21 = decompress16(f111);
		float d22 = decompress16(f112);
		
		float a = FastMath.getAngle(new Vector2f(f1, f2));
		float a2 = FastMath.getAngle(new Vector2f(d21, d22));
		
		System.out.println("d1=" + d21 + ",d2=" + d22 + "\na1=" + a + ",a2=" + a2);
	}
}
